package org.dwpd.config;

import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.socket.WebSocketSession;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;


// 通过这个类来记录当前用户在线状态(维护了 userId 和 WebSocketSession 之间的映射)
@Slf4j
@RestController
public class OnlineUserManger {

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    // 此处这个哈希表要考虑到线程安全问题
    private ConcurrentHashMap<Integer, WebSocketSession> sessions = new ConcurrentHashMap<>();

    // 接收同一用户帖的用户访问信息
    private ConcurrentHashMap<Integer, List<WebSocketSession>> messageSessions = new ConcurrentHashMap<>();

    // 1. 用户上线，给这个哈希表插入键值对
    public void online(Integer userId, Integer messageId, WebSocketSession session, boolean typeJudge) {

        if (typeJudge) {
//            if (sessions.get(userId) != null ) { // 若用户已经在线，则不记录这个映射关系
//                log.info("当前[用户{}] 已经被登录，登录失败!", userId);
//                return;
//            }
            session.getAttributes().put("userId", userId);
            sessions.put(userId, session);
            log.info("[用户{}] 上线", userId);
        }
        else {
            log.info("[用户{}] 进入用户帖: {}", userId, messageId);
            session.getAttributes().put("messageId", messageId);
            if (messageSessions.get(messageId) != null && !messageSessions.get(messageId).contains(session)) {
                messageSessions.get(messageId).add(session);
            }
            else {
                List<WebSocketSession> list = new ArrayList<>();
                list.add(session);
                messageSessions.put(messageId, list);
            }
        }
    }

    // 2. 用户下线操作
    public void offline(Integer userId, WebSocketSession session, String key) {

        Integer messageId = (Integer) session.getAttributes().get("messageId");
        // 2.1 用户下线，针对这个哈希表进行删除元素
        if (userId.equals(session.getAttributes().get("userId")) && messageId == null)
        {
            WebSocketSession existSession = sessions.get(userId);
            if (existSession == session) {
//                log.info("existSession：{}", existSession);
//                log.info("session：{}", session);
                // 如果两个session是同一个才能进行下线操作
                while(sessions.containsKey(userId)) {
                    log.info("sessions 移除 用户Id:{} 的 session：{}", userId, sessions.get(userId));
                    sessions.remove(userId);
                }
//                log.info("userId Sessions:{}", sessions.get(userId));
                // 删除缓存中的用户登录数据
//                stringRedisTemplate.delete(key);
                log.info("[用户{}] 下线", userId);
            }
        }
        else {
            // 2.2 用户离开详情页，删除 messageSessions 中的 session
            List<WebSocketSession> list = messageSessions.get(messageId);
            if (list != null && list.contains(session)) {
                boolean judge = list.remove(session);
                if (judge) {
                    log.info("[用户{}] 离开详情页, 断开页面连接: {}", userId, session.getAttributes().get("messageId"));
                }
            }
        }
    }


    // 3. 锁帖后用户帖中的session集体下线，上座用户需重新进入详情页建立连接
    public void offLineMessage(Integer messageId) {
        messageSessions.remove(messageId);
    }

    // 4. 根据 userId 获取到 WebSocketSession
    public WebSocketSession getSession(Integer userId) {
        return sessions.get(userId); //注意：这里返回的时候若用户为多开状态返回的不是null
    }

    // 5. 根据 messageId 获取点击过当前用户帖的 用户WebSocketSession对象
    public List<WebSocketSession> getSessionByMessageId(Integer messageId) {
        return messageSessions.get(messageId);
    }
}
